home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
apps
/
gmemusage
/
inode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
9KB
|
437 lines
/*
* inode.c
*
* Stuff for translating (dev,inode) pairs to file names
*
* Stolen from memusage programs
*
* Copyright 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include "process.h"
#include "draw.h"
#define INODEFILE ".gmemusage.inodes"
#define INODEFILETMP ".gmemusage.inodes.tmp"
#define DEFUSAGEPATH \
"/usr/ToolTalk:/usr/bin:/usr/lib:/usr/local:/usr/Cadmin:"\
"/usr/CaseVision:/usr/sbin:/usr/bsd:/usr/etc:/lib:"\
"/sbin:/bin:/etc:/usr/gfx "
#define PATHSEP ";,: "
#define FINDCMD "find "
#define FINDARGS "-type f \\( -perm -0100 -o -name \\*so\\* \\) -print "
#define FINDMUNGE " | xargs /sbin/ls -lLid | " \
"sed -e /fonts/d -e /terminfo/d | " \
"awk '{printf \"%d %s\\n\", $1, $10 }' "\
";"\
"echo "\
"/dev/zero "\
"| xargs /sbin/ls -lLid | "\
"awk '{printf \"%d %s\\n\", $1, $11 }'"
struct inrec {
struct inrec *next;
long inode;
dev_t rdev;
char *name;
};
static struct inrec *inodes;
static char *inodePath = NULL;
static char *inodePathTmp = NULL;
static void
MakePaths(void)
{
char *home;
if (!inodePath) {
home = getenv("HOME");
if (!home) {
home = "/var/tmp";
}
/*
* 2 == 1 ('/') + 1 ('\0')
*/
inodePath = malloc(strlen(home) + strlen(INODEFILE) + 2);
sprintf(inodePath, "%s/%s", home, INODEFILE);
inodePathTmp = malloc(strlen(home) + strlen(INODEFILETMP) + 2);
sprintf(inodePathTmp, "%s/%s", home, INODEFILETMP);
}
}
/*
* static char *
* basename(char *path)
*
* Description:
* Get the base file name of a path. Local so I don't have to
* suck in libgen just for this one trivial fuction.
*
* Parameters:
* path
*
* Returns:
* Pointer to basename of path (not duplicated!)
*/
static char *
basename(char *path)
{
char *slash;
slash = strrchr(path, '/');
return slash ? slash + 1 : path;
}
static dev_t
easy_stat (char *path)
{
struct stat statbuf;
if (stat (path, &statbuf) != 0)
return -1;
return statbuf.st_dev;
}
static dev_t
get_device (char *path)
{
struct stat st;
char buff[MAXPATHLEN + 12], str[MAXPATHLEN], buf[256];
FILE *fp;
dev_t i;
if ((i = easy_stat(path)) > 0)
return i;
sprintf (buff, "/etc/devnm %s", path, getpid());
if ((fp = popen(buff, "r")) == NULL) {
perror("popen");
return -1;
}
setbuffer(fp, buf, sizeof buf);
fscanf (fp, "%s", str);
pclose (fp);
if (strcmp (str, "devnm:") == 0) {
return (-1);
}
if (strncmp (str, "/dev/", 5) != 0 &&
strchr (str, ':') == NULL) {
strcpy (buff, "/dev/");
} else {
strcpy (buff, "");
}
strcat (buff, str);
if (lstat (buff, &st) == 0 &&
(st.st_mode & S_IFMT) == S_IFBLK) {
return (st.st_rdev);
} else {
perror ("get_device: lstat");
return (-1);
}
}
/*
* static int
* BuildInodeTable(void)
*
* Description:
* Find a whole bunch of files, and get their inode numbers
*
* Returns:
* 0 if successful, -1 if error
*/
static int
BuildInodeTable(void)
{
dev_t ndev;
FILE *fp, *inodefp;
long inode;
char str[256], *findCmd, *usagePath, *dir;
char buf1[BUFSIZ], buf2[BUFSIZ];
pid_t pid;
int errfd;
/*
* use usagePath as the path to look for executables
*/
usagePath = getenv("USAGEPATH");
if (!usagePath) {
usagePath = DEFUSAGEPATH;
}
/*
* Dup it because strtok is going to modify it
*/
usagePath = strdup(usagePath);
findCmd = malloc(strlen(usagePath) + strlen(FINDCMD)
+ strlen(FINDARGS) + strlen(FINDMUNGE) + 1);
strcpy(findCmd, FINDCMD);
for (dir = strtok(usagePath, PATHSEP); dir;
dir = strtok(NULL, PATHSEP)) {
strcat(findCmd, dir);
strcat(findCmd, " ");
}
strcat(findCmd, FINDARGS);
strcat(findCmd, FINDMUNGE);
/*
* Save our stderr for after the find command, and redirect stderr
* to /dev/null while running find. This is so that the user
* doesn't see find's error messages when it can't find things in
* our list.
*/
errfd = dup(2);
close(2);
(void)open("/dev/null", O_WRONLY);
if ((fp = popen(findCmd, "r")) == NULL) {
dup2(errfd, 2);
close(errfd);
perror("popen");
return -1;
}
setbuffer(fp, buf1, sizeof buf1);
/*
* Swap euid and uid, so we don't create any files that someone
* with our uid couldn't create.
*/
(void)setreuid(geteuid(), getuid());
if ((inodefp = fopen(inodePathTmp, "w")) == NULL) {
pclose(fp);
dup2(errfd, 2);
close(errfd);
(void)setreuid(geteuid(), getuid());
perror("fopen");
return -1;
}
setbuffer(fp, buf2, sizeof buf2);
while (fscanf (fp, "%d %s\n", &inode, str) == 2) {
ndev = get_device (str);
fprintf (inodefp, "%d %d %s\n", ndev, inode, str);
}
pclose (fp);
fclose(inodefp);
/*
* Restore stderr
*/
dup2(errfd, 2);
close(errfd);
/*
* We don't create the actual database unless all has gone well.
*/
(void)unlink(inodePath);
if (link(inodePathTmp, inodePath) == -1) {
perror("link");
}
if (unlink(inodePathTmp) == -1) {
perror("unlink");
}
/*
* Swap back so that we can open everything in /proc
*/
(void)setreuid(geteuid(), getuid());
return 0;
}
/*
* static void
* add_inode(long inode, dev_t rdev, char *str)
*
* Description:
* Add an inode to the internal list
*
* Parameters:
* inode inode to add
* rdev dev to add
* str name to add
*/
static void
add_inode(long inode, dev_t rdev, char *str)
{
struct inrec *new;
new = (struct inrec *)malloc(sizeof (struct inrec));
new->next = inodes;
new->inode = inode;
new->rdev = rdev;
new->name = strdup(str);
/*
* Be careful! InodeLookup relies on the fact that the new
* inode goes at the head of the list; if you change this,
* make sure to fix InodeLookup.
*/
inodes = new;
}
/*
* Add dynamic paths into dev/ino map list
*/
static void
prdynpaths(void)
{
static char *paths[] = { "/var/tmp/.Xshmtrans0",
"/tmp/.cadminOSSharedArena",
NULL };
register int i;
struct stat statd;
/* Add elements to the list */
for (i = 0; paths[i] != NULL; ++i) {
if (stat(paths[i], &statd) < 0)
continue;
add_inode (statd.st_dev, statd.st_ino, paths[i]);
}
}
/*
* int
* InodeInit(void)
*
* Description:
* Initialize inode table. If it exists and is newer than /unix,
* read it in. Otherwise, create it.
*
* Returns:
* 0 if successful, -1 if error
*/
int
InodeInit(void)
{
struct stat stunix, stinodes;
char str[MAXPATHLEN], buffer[BUFSIZ];
int rdev, inode;
FILE *fp;
MakePaths();
if (stat("/unix", &stunix) == -1) {
perror("/unix");
return -1;
}
if (stat(inodePath, &stinodes) == -1 ||
stunix.st_mtime > stinodes.st_mtime) {
WaitMessage("Building inode database. This will take a while,",
"but only has to be done once.");
if (BuildInodeTable() == -1) {
return -1;
}
}
if ((fp = fopen(inodePath, "r")) == NULL) {
perror("fopen");
return -1;
}
setbuffer(fp, buffer, sizeof buffer);
while (fscanf(fp,"%d %d %s\n",&rdev,&inode,str) == 3) {
add_inode (inode, rdev, basename(str));
}
fclose(fp);
prdynpaths();
return 0;
}
/*
* Given a vnode at address vloc, find a corresponding path name
*/
char *
InodeLookup(int rdev, int inode)
{
struct inrec *current;
FILE *fp;
static char buf[100];
for (current = inodes; current; current = current->next)
if (current->inode == inode && current->rdev == rdev)
return current->name;
sprintf(buf, "#%d", inode);
add_inode(inode, rdev, buf);
return inodes->name; /* rely on side effect of add_indode */
}
/*
* int
* FindInode(char *str, dev_t *rdev, ino_t *ino)
*
* Description:
* Given a string, find the inode and device number
*
* Parameters:
* str string to find device and inode of
* rdev gets device
* ino gets inode
*
* Returns:
* 0 if successful, -1 if error
*/
int
FindInode(char *str, dev_t *rdev, ino_t *ino)
{
struct inrec *current;
for (current = inodes; current; current = current->next)
if (strcmp(current->name, str) == NULL) {
if (rdev) *rdev = current->rdev;
if (ino) *ino = current->inode;
return 0;
}
return -1;
}
int
InvalidateInodeTable(void)
{
MakePaths();
(void)unlink(inodePath);
(void)unlink(inodePathTmp);
}